package com.yum.Iterator.List.YArrayList.YLinkedList;

import com.yum.Iterator.Collection.YCollection;
import com.yum.Iterator.List.YList;

import java.util.Iterator;
import java.util.NoSuchElementException;

public class YLinkedList<E> implements YList {

    transient int size = 0;

    /**
     * 操作数
     */
    transient int modCount = 0;

    /**
     * 第一个YNote
     */
    transient YNote<E> first;

    /**
     * 最后一个YNote
     */
    transient YNote<E> last;

    /**
     * E:值
     * next:下一个YNote
     * pre:上一个YNote
     * @param <E>
     */
    private static class YNote<E>{
        E value;
        YNote<E> next;
        YNote<E> pre;

        public YNote(E value, YNote<E> next, YNote<E> pre) {
            this.value = value;
            this.next = next;
            this.pre = pre;
        }
    }


    @Override
    public int size() {
        return size;
    }

    @Override
    public Object[] toArray(Object[] a) {
        return new Object[0];
    }

    @Override
    public boolean add(Object value) {
        lastEleAdd((E) value);
        return true;
    }

    @Override
    public boolean addAll(YCollection Yc) {
        return false;
    }

    @Override
    public void clear() {
        for(YNote<E> x=first;x!=null;){
            YNote<E> Next = x.next;
            x.value = null;
            x.next = null;
            x.pre = null;
            x = Next;
        }
        first = last = null;
        size = 0;
        modCount++;
    }

    @Override
    public boolean contains(Object o) {
        return indexOf(o) != -1;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    public E remove(int index){
        checkIndexOfSize(index);
        return deleteNoteByNote(getNote(index));
    }

    @Override
    public boolean remove(Object o) {
        if(o == null){
            for(YNote<E> ele = first;ele!=null;ele = ele.next){
                if(ele.value == null){
                    deleteNoteByNote(ele);
                    return true;
                }
            }
        }
        else {
            for(YNote<E> ele = first;ele!=null;ele =ele.next){
                if(ele.value.equals(o)){
                    deleteNoteByNote(ele);
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    public boolean removeAll(YCollection Yc) {
        return false;
    }

    @Override
    public boolean contatinsAll(YCollection Yc) {
        return false;
    }


    public E getValueFirst(){
        if(first != null){
            return first.value;
        }
        throw new NoSuchElementException();
    }

    public E getValueLast(){
        if(last != null){
            return last.value;
        }
        throw new NoSuchElementException();
    }

    @Override
    public E getValue(int index) {
        checkIndexOfSize(index);
        return getNote(index).value;
    }

    @Override
    public boolean setValue(int index, Object value) {
        checkIndexOfSize(index);
        YNote<E> newNote = getNote(index);
        newNote.value = (E)value;
        return true;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public Object clone() {
        return null;
    }


    @Override
    public int indexOf(Object value) {
        int index = 0;
        if(value == null){
            for(YNote<E> yNote=first;yNote!=null;yNote = yNote.next){
                if(yNote.value == null){
                    return index;
                }
                index++;
            }
        }
        else {
            for (YNote<E> yNote=first;yNote!=null;yNote = yNote.next){
                if (yNote.value.equals(value)){
                    return index;
                }
                index++;
            }
        }
        return -1;
    }

    @Override
    public String toString() {
        StringBuffer sb = new StringBuffer("[");
        for(YNote<E> ele = first;ele!=null;ele = ele.next){
            sb.append(ele.value.toString());
            if(ele.next != null){
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    @Override
    public int lastIndexOf(Object value) {
        return 0;
    }

    @Override
    public Iterator iterator() {
        return null;
    }

    /**
     * 删除对应的YNote 链表的删除非常方便 只要将YNote和YNote.next和YNote.pre的next和pre从新绑定即可
     * @param yNote YNote
     * @return 值
     */
    private E deleteNoteByNote(YNote<E> yNote){
        final E ele = yNote.value;
        final YNote<E> Next = yNote.next;
        final YNote<E> Prev = yNote.pre;
        if(Prev == null){
            first = Next;
        }else {
            Prev.next = Next;
            yNote.next = null;
        }
        if(Next == null){
            last = Prev;
        }
        else {
            Next.pre = Prev;
            yNote.next = null;
        }
        yNote.value = null;
        size--;
        modCount++;
        return ele;
    }

    private YNote<E> getNote(int index){
        //根据index的大小来判断是从链表前面往后找 还是从链表后面往前找 可以提高效率
        if(index < (size >> 1)){
            YNote<E> result = first;
            for(int i=0;i<index;i++){
                result = result.next;
            }
            return result;
        }
        else {
            YNote<E> result = last;
            for(int i=size-1;i>0;i--){
                result = result.pre;
            }
            return result;
        }
    }

    /**
     * 在链表的后面添加值
     * @param e 值
     */
    private void lastEleAdd(E e){
        final YNote<E> lastNode = last;
        //新建YNote默认 将lasttNote设置为newNode的上一个YNote
        final YNote<E> newNote = new YNote<>(e,null,lastNode);
        last = newNote;
        if(lastNode == null){
            first = newNote;
        }
        else {
            lastNode.next = newNote;
        }
        size++;
        modCount++;
    }


    private void checkIndexOfSize(int index){
        if(index > size){
            throw new IllegalArgumentException("长度错误");
        }
    }
}
